using Gateway.Common.Models;
using Gateway.Domain.Entities;
using Gateway.IApplication.BaseInput;
using Gateway.IApplication.Tenant;
using Gateway.IApplication.Tenant.Input;
using Gateway.IRepositories;

namespace Gateway.Application;

/// <summary>
/// 租户服务
/// </summary>
public class TenantApp : ITenantApp
{
    private readonly IAppRepository<Tenant> _repository;
    private readonly IUnitOfWork _unitOfWork;
    /// <summary>
    /// 
    /// </summary>
    /// <param name="repository"></param>
    /// <param name="unitOfWork"></param>
    public TenantApp(IAppRepository<Tenant> repository, IUnitOfWork unitOfWork)
    {
        _repository = repository;
        _unitOfWork = unitOfWork;
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    /// <exception cref="MyException"></exception>
    public async Task<bool> Add(CreateTenantInput input)
    {
        var tenantCode = GenerateTenantCode();
        var existAgency = await _repository.FirstOrDefaultAsync(x => x.TenantCode == tenantCode);
        if (existAgency != null)
        {
            throw new MyException("租户专属ID已存在");
        }

        existAgency = await _repository.FirstOrDefaultAsync(x => x.TenantName == input.TenantName);
        if (existAgency != null)
        {
            throw new MyException("租户名称重复，请更换名称");
        }

        existAgency = await _repository.FirstOrDefaultAsync(x => x.TenantDomain == input.TenantDomain.Trim().ToLower());
        if (existAgency != null)
        {
            throw new MyException("租户域名不可重复");
        }

        var tenant = new Domain.Entities.Tenant(
            tenantCode: tenantCode,
            tenantName: input.TenantName,
            tenantAliasName: input.TenantAliasName,
            contactName: input.ContactName,
            contactPhone: input.ContactPhone,
            expireTime: input.ExpireTime,
            tenantAddress: input.TenantAddress,
            tenantMail: input.TenantMail,
            tenantDomain: input.TenantDomain,
            logoUrl: input.LogoUrl
        );
        await _repository.AddAsync(tenant);
        await _unitOfWork.CommitAsync();
     
        return true;
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    /// <exception cref="MyException"></exception>
    public async Task<bool> Update(UpdateTenantInput input)
    {
        var tenant = await _repository.GetAsync(input.TenantId);
        if (tenant is null) throw new MyException("租户不存在");
        var existAgency =
            await _repository.FirstOrDefaultAsync(x => x.TenantName == input.TenantName && x.Id != input.TenantId);
        if (existAgency != null)
        {
            throw new MyException("租户名称重复，请更换名称");
        }

        existAgency = await _repository.FirstOrDefaultAsync(x =>
            x.TenantDomain == input.TenantDomain.Trim().ToLower() && x.Id != input.TenantId);
        if (existAgency != null)
        {
            throw new MyException("租户域名不可重复");
        }

        tenant.Update(
            tenantName: input.TenantName,
            tenantAliasName: input.TenantAliasName,
            contactName: input.ContactName,
            contactPhone: input.ContactPhone,
            expireTime: input.ExpireTime,
            tenantAddress: input.TenantAddress,
            tenantMail: input.TenantMail,
            tenantDomain: input.TenantDomain,
            logoUrl: input.LogoUrl
        );
        await _repository.UpdateAsync(tenant);
        await _unitOfWork.CommitAsync();
        return true;
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    /// <exception cref="MyException"></exception>
    public async Task<bool> Disable(DisableInput input)
    {
        var tenant = await _repository.GetAsync(input.Id);
        if (tenant is null) throw new MyException("租户不存在");
        tenant.SetDisabled(input.Disable);
        await _repository.UpdateAsync(tenant);
        await _unitOfWork.CommitAsync();
        return true;
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    /// <exception cref="MyException"></exception>
    public async Task<bool> Remove(RemoveInput input)
    {
        var tenant = await _repository.GetAsync(input.Id);
        if (tenant is null) throw new MyException("租户不存在");
        tenant.SetDeleted();
        await _repository.UpdateAsync(tenant);
        await _unitOfWork.CommitAsync();
        return true;
    }


    /// <summary>
    /// 生成企业代码
    /// </summary>
    /// <returns></returns>
    private string GenerateTenantCode()
    {
        System.Threading.Thread.Sleep(3);
        var pattern = new char[]
        {
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
            'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
        };
        var result = "";
        var n = pattern.Length;
        var random = new Random(~unchecked((int)DateTime.Now.Ticks));
        for (var i = 0; i < 8; i++)
        {
            var rnd = random.Next(0, n);
            result += pattern[rnd];
        }

        return result;
    }
}